﻿using Furion;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UpperComputer.Core.Entities;
using YFurion.Application;
using YFurion.Application.EFCore.Extensions;
using YFurion.Extensions;
using YFurion.Utils.Extensions;

namespace UpperComputer.Application
{
    public class LoginInOrOutLogService : EFCoreApplicationService<LoginInOrOutLog, LoginInOrOutLogDto, long, LoginInOrOutLogResultRequestDto>, ILoginInOrOutLogService
    {
        protected override IQueryable<LoginInOrOutLog> CreateFilteredQuery(LoginInOrOutLogResultRequestDto input)
        {
            var resultData = base.CreateFilteredQuery(input)
                .WhereIf(!input.Account.IsNullOrWhiteSpace(), l => l.Account.StartsWith(input.Account))
                .WhereIf(input.StartTime != null, l => l.OperationTime >= input.StartTime)
                .WhereIf(input.EndTime != null, l => l.OperationTime <= input.EndTime);
            return resultData;
        }

        public async Task<LoginInOrOutLogDto> CreateLog(BaseUserDto input, CancellationToken cancellationToken = default)
        {
            LoginInOrOutLogDto loginInOrOutLogDto = new LoginInOrOutLogDto
            {
                LoginInOrOut = true,
                Ip = App.HttpContext.GetClientIPv4(),
                UserId = input.Id,
                UserName = input.DisplayName,
                Account = input.Account,
                OperationTime = DateTime.Now
            };
            return await base.Post(loginInOrOutLogDto, cancellationToken);
        }

        public async Task<LoginInOrOutLogDto> CreateLogout(CancellationToken cancellationToken = default)
        {
            LoginInOrOutLog loginInOrOut = await SlaveRepository.FindOrDefaultAsync(YSession.SubjectId, cancellationToken);
            if (loginInOrOut != null)
            {
                loginInOrOut.IsExpired = true;
                await UpdateAsync(loginInOrOut, cancellationToken);
            }
            LoginInOrOutLogDto loginInOrOutLogDto = new LoginInOrOutLogDto
            {
                LoginInOrOut = false,
                Ip = App.HttpContext.GetClientIPv4(),
                UserId = YSession.SubjectId,
                UserName = YSession.UserName,
                Account = YSession.Account,
                OperationTime = DateTime.Now,
                IsExpired = true
            };
            return await base.Post(loginInOrOutLogDto, cancellationToken);
        }
    }
}
